package com.code.wflow.controller;

import com.alibaba.fastjson2.JSON;
import com.code.wflow.api.UserApi;
import com.code.wflow.common.RequestContextHolder;
import com.code.wflow.constants.*;
import com.code.wflow.handler.InstanceActuator;
import com.code.wflow.model.*;
import com.code.wflow.node.ApprovalNodeProperties;
import com.code.wflow.service.*;
import com.code.wflow.utils.BeanCopierUtils;
import com.code.wflow.wrapper.Result;
import com.code.wflow.wrapper.request.HandleTaskRequest;
import com.code.wflow.wrapper.request.QueryTaskRequest;
import com.code.wflow.wrapper.request.TaskIdRequest;
import com.code.wflow.wrapper.response.FormItemVO;
import com.code.wflow.wrapper.response.QueryTaskDetailVO;
import com.code.wflow.wrapper.response.QueryTaskVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 任务相关
 *
 * @author ggh
 * @date 2022/11/8
 */
@RequestMapping(value = "/task")
@RestController
public class TaskController {

    @Autowired
    private InstanceService instanceService;
    @Autowired
    private InstanceNodeService instanceNodeService;
    @Autowired
    private InstanceNodeDetailService instanceNodeDetailService;
    @Autowired
    private WorkflowNodeService nodeService;
    @Autowired
    private WorkflowTaskService taskService;
    @Autowired
    private FormItemService formItemService;

    @Autowired
    private InstanceActuator instanceActuator;
    @Autowired
    private UserApi userApi;

    /**
     * 查询代办任务
     *
     * @param request
     * @return
     */
    @RequestMapping(value = "/queryTodoTask")
    public Result<List<QueryTaskVO>> queryTodoTask(@RequestBody QueryTaskRequest request) {
        if (request == null || request.getType() == null) {
            return Result.failure(ResultCode.PARAM_LACK);
        }
        try {
            List<WorkflowTask> taskList = taskService.queryByUserId(RequestContextHolder.getContext().getUserId(), request.getType(), TaskFinishEnum.FALSE.isFinish());

            if (CollectionUtils.isEmpty(taskList)) {
                return Result.ok(null);
            }

            List<Long> instanceIdList = taskList.stream().map(WorkflowTask::getInstanceId).collect(Collectors.toList());
            List<Instance> instanceList = instanceService.queryDetailByIdList(instanceIdList);
            Map<Long, Instance> instanceMap = instanceList.stream().collect(Collectors.toMap(Instance::getId, Function.identity()));

            List<QueryTaskVO> taskVOList = new ArrayList<>(taskList.size());
            taskList.forEach((task) -> {
                Instance instance = instanceMap.get(task.getInstanceId());

                QueryTaskVO taskVO = BeanCopierUtils.copy(task, QueryTaskVO.class);
                taskVO.setWorkflowName(instance.getWorkflowName());
                taskVO.setStartTime(instance.getStartTime());
                taskVOList.add(taskVO);
            });

            return Result.ok(taskVOList);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return Result.failure(ResultCode.TASK_QUERY_ERROR);
    }

    /**
     * 查看任务详情
     *
     * @param request
     * @return
     */
    @RequestMapping(value = "/queryTaskDetail")
    public Result<QueryTaskDetailVO> queryTaskDetail(@RequestBody TaskIdRequest request) {
        if (request == null || request.getTaskId() == null) {
            return Result.failure(ResultCode.PARAM_LACK);
        }
        try {
            WorkflowTask task = taskService.queryById(request.getTaskId());
            if (task == null) {
                return Result.failure(ResultCode.TASK_NOT_EXIST);
            }

            Instance instance = instanceService.queryDetailById(task.getInstanceId());
            if (instance == null) {
                return Result.failure(ResultCode.TASK_NOT_EXIST);
            }

            AclUser aclUser = userApi.selectById(instance.getCreateUserId());

            QueryTaskDetailVO detailVO = BeanCopierUtils.copy(task, QueryTaskDetailVO.class);
            detailVO.setRemark(instance.getRemark());
            detailVO.setStartTime(instance.getStartTime());
            detailVO.setWorkflowName(instance.getWorkflowName());
            detailVO.setStartName(aclUser.getName());

            List<FormItem> formItemList = formItemService.queryByWorkflowId(instance.getWorkflowId());
            List<FormItemVO> formItemVOList = BeanCopierUtils.copyList(formItemList, FormItemVO.class);
            detailVO.setFormItems(formItemVOList);
            detailVO.setBusinessData(instance.getBusinessData());

            return Result.ok(detailVO);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return Result.failure(ResultCode.TASK_QUERY_ERROR);
    }

    /**
     * 审批任务
     *
     * @param request
     * @return
     */
    @RequestMapping(value = "/approvalTask")
    public Result<String> approvalTask(@RequestBody HandleTaskRequest request) {
        if (request == null || request.getTaskId() == null || request.getStatus() == null || !HandleTaskStatusEnum.handlerTask(request.getStatus())) {
            return Result.failure(ResultCode.PARAM_LACK);
        }
        try {
            WorkflowTask task = taskService.queryById(request.getTaskId());
            // 检查任务类型与所属状态是否相符
            if (task != null && TaskFinishEnum.FALSE.isFinish().equals(task.getFinish())
                    && !TaskStatusEnum.TODO.getVal().equals(task.getStatus())) {
                return Result.failure(ResultCode.TASK_STATUS_DISCREPANCY);
            }

            // 检查任务执行人和登录人是否一致
            Long userId = RequestContextHolder.getContext().getUserId();
            if (!userId.equals(task.getExecutorId())) {
                return Result.failure(ResultCode.TASK_EXECUTOR_DISCREPANCY);
            }

            // 检查流程是否结束
            InstanceNodeDetail instanceNodeDetail = instanceNodeDetailService.queryById(task.getInstanceNodeDetailId());
            Instance instance = instanceService.queryDetailById(task.getInstanceId());

            if (instance == null || instance.getStage().equals(InstanceStage.END.getVal())) {
                return Result.failure(ResultCode.INSTANCE_END);
            }

            // 检查节点是否已经结束
            InstanceNode instanceNode = instanceNodeService.queryById(instanceNodeDetail.getInstanceNodeId());
            if (!InstanceNodeStage.PROGRESSING.getVal().equals(instanceNode.getStage())) {
                return Result.failure(ResultCode.NODE_PROCESS_ERROR);
            }

            WorkflowNode node = nodeService.queryById(instanceNode.getWorkflowNodeId());
            ApprovalNodeProperties properties = JSON.parseObject(node.getProps(), ApprovalNodeProperties.class);

            // 设置任务与节点详情信息
            task.setStatus(TaskStatusEnum.HANDLED.getVal());
            instanceNodeDetail.setStatus(request.getStatus());
            instanceNodeDetail.setRemark(request.getRemark());

            boolean result = false;
            // 判断当前节点的审批类型，以及其他人的审批信息
            if (ApprovaModeEnum.OR.getMode().equals(properties.getMode())) {
                // 如果是或签节点判断审批状态和其他人的审批状态
                if (HandleTaskStatusEnum.AGREE.getType().equals(request.getStatus())) {
                    instanceNode.setStage(InstanceNodeStage.END.getVal());
                    instanceNode.setStatus(InstanceNodeStatus.PASS.getVal());
                    instanceNode.setEndTime(new Date());

                    result = taskService.handleTask(task, instanceNodeDetail, instanceNode, null, true);
                } else {
                    // 如果审批状态为拒绝查询其他人是否审批
                    List<Byte> instanceNodeDetailStatusList = instanceNodeDetailService.queryStatusByInstanceNode(instanceNode.getId());
                    long refusedCount = instanceNodeDetailStatusList.stream().filter((detailStatus) -> HandleTaskStatusEnum.REFUSE.getType().equals(detailStatus)).count();

                    if (refusedCount == instanceNodeDetailStatusList.size() - 1) {
                        // 除自己以外所有人都拒绝则拒绝节点
                        instanceNode.setStage(InstanceNodeStage.END.getVal());
                        instanceNode.setStatus(InstanceNodeStatus.NO_PASS.getVal());
                        instanceNode.setEndTime(new Date());

                        // 设置流程的结束状态
                        instance.setStage(InstanceStage.END.getVal());
                        instance.setStatus(InstanceStatus.REJECT.getVal());
                        instance.setEndTime(new Date());
                        result = taskService.handleTask(task, instanceNodeDetail, instanceNode, instance, false);
                    } else {
                        //如果还有人未审批，则直接返回即可;此时不需要判断是否存在有人同意，因为如果中途有人同意则该节点直接完成
                        result = taskService.handleTask(task, instanceNodeDetail, null, null, false);
                    }
                }
            } else if (ApprovaModeEnum.AND.getMode().equals(properties.getMode())) {
                // 如果是会签节点判断审批状态和其他人的审批状态
                if (HandleTaskStatusEnum.REFUSE.getType().equals(request.getStatus())) {
                    // 如果审批条件是拒绝，则直接结束流程
                    instanceNode.setStage(InstanceNodeStage.END.getVal());
                    instanceNode.setStatus(InstanceNodeStatus.NO_PASS.getVal());
                    instanceNode.setEndTime(new Date());
                    // 设置流程的结束状态
                    instance.setStage(InstanceStage.END.getVal());
                    instance.setStatus(InstanceStatus.REJECT.getVal());
                    instance.setEndTime(new Date());

                    result = taskService.handleTask(task, instanceNodeDetail, instanceNode, instance, false);
                } else {
                    // 如果审批状态为同意查询其他人是否审批
                    List<Byte> instanceNodeDetailStatusList = instanceNodeDetailService.queryStatusByInstanceNode(instanceNode.getId());
                    long agreeCount = instanceNodeDetailStatusList.stream().filter((detailStatus) -> HandleTaskStatusEnum.AGREE.getType().equals(detailStatus)).count();

                    if (agreeCount == instanceNodeDetailStatusList.size() - 1) {
                        // 除自己以外所有人都同意了则该节点通过
                        instanceNode.setStage(InstanceNodeStage.END.getVal());
                        instanceNode.setStatus(InstanceNodeStatus.PASS.getVal());
                        instanceNode.setEndTime(new Date());

                        result = taskService.handleTask(task, instanceNodeDetail, instanceNode, null, true);
                    } else {
                        //如果还有人未审批，则直接返回即可;此时不需要判断是否存在有人拒绝，因为如果中途有人拒绝则该节点直接结束
                        result = taskService.handleTask(task, instanceNodeDetail, null, null, false);
                    }
                }
            } else {
                return Result.failure(ResultCode.TASK_APPROVAL_ERROR);
            }

            if (result) {
                return Result.ok("任务审批成功");
            } else {
                return Result.failure(ResultCode.TASK_APPROVAL_ERROR);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return Result.failure(ResultCode.TASK_APPROVAL_ERROR);
    }

    /**
     * 读取任务
     *
     * @param request
     * @return
     */
    @RequestMapping(value = "/readTask")
    public Result<String> readTask(@RequestBody HandleTaskRequest request) {
        if (request == null || request.getTaskId() == null) {
            return Result.failure(ResultCode.PARAM_LACK);
        }
        try {
            WorkflowTask task = taskService.queryById(request.getTaskId());
            if (task == null) {
                return Result.failure(ResultCode.TASK_NOT_EXIST);
            }

            // 检查任务类型与所属状态是否相符
            if (task != null && TaskFinishEnum.FALSE.isFinish().equals(task.getFinish())
                    && !TaskStatusEnum.UNREAD.getVal().equals(task.getStatus())) {
                return Result.failure(ResultCode.TASK_STATUS_DISCREPANCY);
            }

            // 检查任务执行人和登录人是否一致
            Long userId = RequestContextHolder.getContext().getUserId();
            if (!userId.equals(task.getExecutorId())) {
                return Result.failure(ResultCode.TASK_EXECUTOR_DISCREPANCY);
            }

            InstanceNodeDetail instanceNodeDetail = instanceNodeDetailService.queryById(task.getInstanceNodeDetailId());
            instanceNodeDetail.setStatus(HandleTaskStatusEnum.READED.getType());
            instanceNodeDetail.setRemark(request.getRemark());

            task.setStatus(TaskStatusEnum.READ.getVal());

            boolean result = taskService.handleTask(task, instanceNodeDetail, null, null, false);
            if (result) {
                return Result.ok("任务读取成功");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return Result.failure(ResultCode.TASK_READ_ERROR);
    }

}
